package com.garbagecode.resultbounds.bounds;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

public class ResultBounds extends RowBounds {
  private String order;
  private TotalCountBounds totalCountBounds;
  private static final ThreadLocal<ResultBounds> context = new ThreadLocal<ResultBounds>();

  public ResultBounds() {

  }

  public ResultBounds(String order) {
    this.order = order;
  }

  public ResultBounds(RowBounds rowBounds) {
    super(rowBounds.getOffset(), rowBounds.getLimit());
  }

  public ResultBounds(int offset, int limit) {
    super(offset, limit);
  }

  public ResultBounds(RowBounds rowBounds, String order) {
    super(rowBounds.getOffset(), rowBounds.getLimit());
    this.order = order;
  }

  public ResultBounds(int offset, int limit, String order) {
    super(offset, limit);
    this.order = order;
  }

  public String getOrder() {
    return order;
  }

  public void setOrder(String order) {
    this.order = order;
  }

  /**
   * 返回符合查询条件的记录总数
   * @param sqlSession
   * @return
   */
  public long getTotal(SqlSession sqlSession) {
    if (totalCountBounds == null) {
      throw new RuntimeException("property'totalCountBounds' is null");
    }

    return totalCountBounds.getTotal(sqlSession);
  }

  public void setTotal(TotalCountBounds total) {
    this.totalCountBounds = total;
  }

  /**
   * 返回当前上下文中的 ResultBounds 对象，
   * 在 resultBounds.apply 方法外调用总是返回 null
   * @return
   */
  public static ResultBounds getCurrentBounds() {
    return context.get();
  }

  /**
   * 使用该 ResultBounds 对象过滤查询结果，resultBounds.apply 方法内的查询
   * 强制使用该 ResultBounds 对象过滤
   * @param applyScope
   * @return
   */
  @SuppressWarnings("unchecked")
  public <T> T apply(ApplyScope applyScope) {
    if (applyScope == null) {
      throw new IllegalArgumentException("applyScope null");
    }

    try {
      context.set(this);

      return (T) applyScope.apply();
    } finally {
      context.remove();
    }
  }

}
